package com.liu.stockmarket.repository.network

import android.util.Log
import androidx.viewbinding.BuildConfig
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.liu.stockmarket.model.*
import com.liu.stockmarket.utils.YYYYMMDD
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.logging.HttpLoggingInterceptor
import java.time.LocalDate

/**
 * 东方财富 相关api
 */
class EasyMoneyRepository {
    private var httpClient: OkHttpClient

    init {
        httpClient = OkHttpClient.Builder()
            .addInterceptor(getHttpLoggingInterceptor()).build()
    }

    /**
     * 如  1.601398 1 上海  0深圳
     */
    fun kline(code: String, endDate: LocalDate): KlineResult? {
        val parameterNames = mapOf(
            "secid" to code, // 1 上海  0深圳
            "klt" to "101",
            "fqt" to "1",
            "lmt" to "20", // 获取数量
            "end" to endDate.YYYYMMDD(),
            "iscca" to "1",
            "fields1" to "f1,f2,f3,f4,f5",
            "fields2" to "f51,f52,f53,f54,f55,f56,f57,f59",
            "ut" to "f057cbcbce2a86e2866ab8877db1d059",
            "forcect" to "1",
        )
        val request = request(KLINE_URL, parameterNames)


        try {
            val response = httpClient.newCall(request).execute()
            val body = response.body
            return if (body == null) {
                null
            } else {
                val responseString = body.string()
                println(responseString)
                val type = object : TypeToken<KlineResult>() {}.type
                Gson().fromJson(responseString, type)
            }
        } catch (e: Exception) {
            Log.e(this.javaClass.name, e.message, e)
        }
        return null

    }


    /**
     * 搜索股票、债券、基金
     */
    fun searchStock(keyword: String): StockSearchResult? {
        val parameterNames = mapOf(
            "appid" to "el1902262",
            "type" to "14",
            "token" to "CCSDCZSDCXYMYZYYSYYXSMDDSMDHHDJT",
            "and14" to "MultiMatch/Name,Code,PinYin/${keyword}/true",
            "returnfields14" to "Name,Code,PinYin,MarketType,JYS,MktNum,JYS4App,MktNum4App,ID,Classify,IsExactMatch,SecurityType,SecurityTypeName",
            "pageIndex14" to "1",
            "pageSize14" to "20",
            "isAssociation14" to "false" + System.currentTimeMillis(),
        )


        val request = request(STOCK_SEARCH_URL, parameterNames)

        try {
            val response = httpClient.newCall(request).execute()
            val body = response.body
            return if (body == null) {
                null
            } else {
                val responseString = body.string()
                println(responseString)
                val type = object : TypeToken<StockSearchResult>() {}.type
                Gson().fromJson(responseString, type)
            }
        } catch (e: Exception) {
            Log.e(this.javaClass.name, e.message, e)
        }
        return null

    }

    /**
     * @param codes  如 0.127043,1.601012,  1:上海，0：深圳
     */
    fun getStockTransactionInfo(codes: String): StockTransactionResult? {
        val parameterNames = mapOf(
            "fltt" to "2",
            "fields" to "f12,f13,f19,f14,f139,f148,f2,f4,f1,f125,f18,f3,f152,f5,f30,f31,f32,f6,f8,f7,f10,f22,f9,f112,f100,f88,f153",
            "ut" to "f057cbcbce2a86e2866ab8877db1d059",
            "secids" to codes // 0 上海，1深圳
        )

        val request = request(STOCK_TRANSACTION_URL, parameterNames)

        try {
            val response = httpClient.newCall(request).execute()
            val body = response.body
            return if (body == null) {
                null
            } else {
                val responseString = body.string()
                println(responseString)
                val type = object : TypeToken<StockTransactionResult>() {}.type
                Gson().fromJson(responseString, type)
            }
        } catch (e: Exception) {
            Log.e(this.javaClass.name, e.message, e)
        }
        return null
    }

    /**
     * 如：111121,121212
     */
    fun getFundTransactionInfo(codes: String): FundTransactionResult? {
        val parameterNames = mapOf(
            "pageIndex" to "1",
            "pageSize" to "200",
            "plat" to "Android",
            "appType" to "ttjj",
            "product" to "EFund",
            "Version" to "1",
            "deviceid" to "5616d643-16a6-4f88-aef1-2f92767e5fbf",
            "Fcodes" to codes,

            )

        val request = request(FUND_TRANSACTION_URL, parameterNames)

        try {
            val response = httpClient.newCall(request).execute()
            val body = response.body
            return if (body == null) {
                null
            } else {
                val responseString = body.string()
                println(responseString)
                val type = object : TypeToken<FundTransactionResult>() {}.type
                Gson().fromJson<FundTransactionResult>(responseString, type)
            }
        } catch (e: Exception) {
            Log.e(this.javaClass.name, e.message, e)
        }
        return null
    }


    /**
     * 指数
     * 上证：1.000001,沪深300：1.000300,深证指数：0.399001,创业板指：0.399006
     */
    fun getCompositeIndex(): StockTransactionResult? {
        return this.getStockTransactionInfo("1.000001,1.000300,0.399001,0.399006")
    }

    fun getStockSF(secid: String): StockInfo? {
        val parameterNames = mapOf(
            "ut" to "fa5fd1943c7b386f172d6893dbfba10b",
            "fltt" to "2",
            "invt" to "2",
            "fields" to "f43,f44,f45,f46,f47,f48,f60",
            "secid" to secid,
        )

        val request = request(STOCK_SF_URL, parameterNames)

        try {
            val response = httpClient.newCall(request).execute()
            val body = response.body
            return if (body == null) {
                null
            } else {
                val responseString = body.string()
                println(responseString)
                val type = object : TypeToken<StockInfo>() {}.type
                Gson().fromJson<StockInfo>(responseString, type)
            }
        } catch (e: Exception) {
            Log.e(this.javaClass.name, e.message, e)
        }
        return null
    }

    fun getNewBond(pageNumber: Int? = 1): NewBondResult? {
        val request = request(NEW_BOND, mapOf("pageNumber" to pageNumber.toString()))

        try {
            val response = httpClient.newCall(request).execute()
            val body = response.body
            return if (body == null) {
                null
            } else {
                val responseString = body.string()
                println(responseString)
                val type = object : TypeToken<NewBondResult>() {}.type
                Gson().fromJson<NewBondResult>(responseString, type)
            }
        } catch (e: Exception) {
            Log.e(this.javaClass.name, e.message, e)
        }
        return null
    }

    fun getQuotation(): QuotationResult? {
        val request = request(QUOTATION_URL, mapOf("_" to System.currentTimeMillis().toString()))

        try {
            val response = httpClient.newCall(request).execute()
            val body = response.body
            return if (body == null) {
                null
            } else {
                val responseString = body.string()
                println(responseString)
                val type = object : TypeToken<QuotationResult>() {}.type
                Gson().fromJson<QuotationResult>(responseString, type)
            }
        } catch (e: Exception) {
            Log.e(this.javaClass.name, e.message, e)
        }
        return null
    }



    private fun request(url: String, parameterNames: Map<String, String>): Request {
        val newBuilder = url.toHttpUrl().newBuilder()

        parameterNames.forEach {
            newBuilder.addEncodedQueryParameter(it.key, it.value)

        }


        return Request.Builder()
            .url(newBuilder.build())
            .addHeader("Content-Type", CONTENT_TYPE)
            .addHeader(
                "User-Agent",
                USER_AGENT
            ).build()
    }

    private fun getHttpLoggingInterceptor(): HttpLoggingInterceptor {
        val logging = HttpLoggingInterceptor()
        if (BuildConfig.DEBUG) {
            logging.level = HttpLoggingInterceptor.Level.BODY
        } else {
            logging.level = HttpLoggingInterceptor.Level.BASIC
        }
        return logging
    }

    companion object {
        const val STOCK_SEARCH_URL = "https://searchapi.eastmoney.com/api/Info/Search"
        const val KLINE_URL = "https://push2his.eastmoney.com/api/qt/stock/kline/get"
        const val STOCK_TRANSACTION_URL = "https://push2.eastmoney.com/api/qt/ulist.np/get"
        const val FUND_TRANSACTION_URL = "https://fundmobapi.eastmoney.com/FundMNewApi/FundMNFInfo"
        const val COMPOSITE_INDEX_URL = "https://push2.eastmoney.com/api/qt/ulist.np/get"
        const val STOCK_SF_URL = "http://push2.eastmoney.com/api/qt/stock/get"

        /**
         * 行业数据
         */
        const val QUOTATION_URL = "http://push2.eastmoney.com/api/qt/clist/get?pn=1&pz=500&po=1&np=1&fields=f12,f13,f14,f62&fid=f62&fs=m:90+t:2"

        const val NEW_BOND =
            "https://datacenter-web.eastmoney.com/api/data/v1/get?sortColumns=PUBLIC_START_DATE&sortTypes=-1&pageSize=50&reportName=RPT_BOND_CB_LIST&columns=ALL&quoteColumns=f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE,f235~10~SECURITY_CODE~TRANSFER_PRICE,f236~10~SECURITY_CODE~TRANSFER_VALUE,f2~10~SECURITY_CODE~CURRENT_BOND_PRICE,f237~10~SECURITY_CODE~TRANSFER_PREMIUM_RATIO,f239~10~SECURITY_CODE~RESALE_TRIG_PRICE,f240~10~SECURITY_CODE~REDEEM_TRIG_PRICE,f23~01~CONVERT_STOCK_CODE~PBV_RATIO&source=WEB&client=WEB"

        const val CONTENT_TYPE = "application/json; charset=utf-8"
        const val USER_AGENT =
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Edg/94.0.992.38"
    }
}